package com.topwalk.datacollect.controller;

import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Base64.Encoder;
import java.util.List;
import java.util.Map;
import java.util.concurrent.LinkedBlockingQueue;

import javax.servlet.http.HttpServletRequest;

import com.topwalk.datacollect.enumI.FactoryEnum;
import com.topwalk.datacollect.factoty.ServerFactory;
import com.topwalk.datacollect.manager.FactoryManager;
import com.topwalk.datacollect.serverResult.BaseModelDecorate;
import com.topwalk.datacollect.server.BaseServer;
import com.topwalk.datacollect.util.SocketCP;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.topwalk.datacollect.config.ApplicationConfig;
import com.topwalk.datacollect.config.HeaderConfig;
import com.topwalk.datacollect.constant.APIConstant;
import com.topwalk.datacollect.util.DateUtil;

@RestController
@RequestMapping("/collectsvc")
public class IncController {
	private static final Logger LOG = LoggerFactory.getLogger(IncController.class);

	@Autowired
	private FactoryManager factoryManager;

	/**
	 * 平台注册信息
	 * @param data
	 * @return
	 */
	@PostMapping(value={"PlatRunState","InnerLinkRunState","BizRunState","DeviceRunState","PlatRegInf","TPlatInnerLinkStatInfo","TPlatBizStatInfo","FileExchangeLog","DBExchangeLog","video","tbsg","PlatAlertInf"})
	public String inc(String data, HttpServletRequest request) {

		// 获取请求接口
		StringBuffer url = request.getRequestURL();
		String remoteHost = request.getRemoteHost();
		int index = url.lastIndexOf("/");
        String api = url.substring(index + 1);
//        String api = "test";
        LOG.info("接收restful："+api);

		ServerFactory serverFactory = (ServerFactory) factoryManager.getFactory(FactoryEnum.SERVER.toString());
		BaseServer<String> serverImpl = serverFactory.getServerImpl(api, String.class);
		String result;
		if (serverImpl != null){
			ArrayList<String> args = new ArrayList<>();
			args.add(data);
			args.add(api);
			result = serverImpl.handleBiz(args);
		}else {
			result = data;
		}

		// 获取发送头信息
		String[] strings = APIConstant.API_TAB_INC.get(api);
		String tableName = strings[0];
		String logTime = strings[1];
		// 设置响应内容
		boolean success = true;
		String time = DateUtil.getCurrentTime("yyyy-MM-dd HH:mm:ss");
		String ok_msg = "{\"collectTime\":\""+time+"\",\"desc\":\"数据采集成功\",\"status\":\"000\"}";
		String ng_msg = "{\"collectTime\":\""+time+"\",\"desc\":\"数据采集失败\",\"status\":\"001\"}";

		// json字符串转map列表
		List<Map<String, Object>> dataList = null;
		ObjectMapper mapper = new ObjectMapper();
		try {
			dataList = mapper.readValue(result,new TypeReference<List<Map<String, Object>>>(){});

		} catch (Exception e) {
			e.printStackTrace();
			return ng_msg;
		}

		String ip = ApplicationConfig.INC_SOCKET_IP;
		int port = ApplicationConfig.INC_SOCKET_PORT;
		// 发送数据
		LinkedBlockingQueue<Socket> socketCP = SocketCP.SOCKET_QUEUE.get(ip+"_"+port);
		Socket socket = null;
		try {
			socket = socketCP.take();// 若获取不到socket，将阻塞
			LOG.info("socketCP.get");
			sendInc(tableName, logTime, socket, dataList);
		} catch (Exception e) {
			success = false;
			LOG.error("发送数据异常: {}", e.getMessage());
			// 认为socket失效，重新建立socket连接
			try {
				if(socket != null){
					socket.close();
				}
			} catch (Exception e1) {
//				e1.printStackTrace();
				LOG.error("socket关闭失败: {}" ,e1.getMessage());
			}finally {
				try {
					socket = new Socket(ip, port);
				} catch (IOException ex) {
//					ex.printStackTrace();
					LOG.error("创建socket异常: {}", ex.getMessage());
				}
			}
			return ng_msg;
		}finally {
			try {
				if(socket != null){
					socketCP.put(socket);
				}else {
					socketCP.put(new Socket(ip, port));
				}

			} catch (Exception e) {
//				e.printStackTrace();
				LOG.error("socketCP.put 发生异常： {}" , e.getMessage());
			}
		}


//		Socket socket = null;
//		try {
//			socket = new Socket(ip,port);
//			socket.setSoTimeout(3 * 60 * 1000);
//			sendInc(tableName, logTime, socket, dataList);
//		} catch (Exception e) {
//			success = false;
//			LOG.error("发送数据异常中断: {}", e.getMessage());
//		}finally {
//			try {
//				if (socket != null){
//					socket.close();
//				}
//			} catch (IOException e) {
//				LOG.error("socket关闭异常: {}", e.getMessage());
//			}
//		}
		
		return success ? ok_msg : ng_msg;
	}
	
	// 发送增量数据
	private void sendInc(String tableName, String logTime, Socket socket, List<Map<String,Object>> dataList) throws Exception{
		ObjectMapper om = new ObjectMapper();
		Encoder encoder = Base64.getEncoder();
		String header = new String(HeaderConfig.INC);
		header = header.replace("$dataType", tableName);
		DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
		for(int i=0; i < dataList.size(); i++){
			// 获取数据
			Map<String, Object> map = dataList.get(i);
			// 设置logTime
			String time = map.get(logTime).toString();
			time = time.replaceAll("[- :T]", "");
			String data = header.replace("$logTime", time);
			// map转json
			String json = om.writeValueAsString(map);
			// json转base64
			String base64 = encoder.encodeToString(json.getBytes("UTF-8"));
			// 添加businessData
			data = data.replace("$businessData", base64);
			// 发送数据
			dos.write((data+"\n").getBytes("UTF-8"));
	        LOG.info("发送flume："+data);
		}
	}

		
}
